package com.x2.modular.export.kit;

import com.x2.core.util.SpringContextHolder;
import com.x2.base.pojo.page.LayuiPageInfo;
import com.x2.core.util.ListUtil;
import com.x2.core.util.MapList;
import com.x2.modular.export.vo.XyExcelDefVO;
import com.x2.modular.export.vo.XyExportExcelItem;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DataDao {
    //定义集合
    private XyExcelDefVO defVO;
    //属性集合
    private List<XyExportExcelItem> mainDisList = new ArrayList<>();
    private List<XyExportExcelItem> bodyDisList = new ArrayList<>();
    //主表数据
    private Map<String, Map<String, Object>> mainMap = new HashMap<>();
    //子表数据
    private MapList<String, Map<String, Object>> bodyList = new MapList<>();
    //主键列表，也维护顺序
    private List<String> idList = new ArrayList<>();

    /**
     * 构造
     *
     * @param pageInfo
     * @param defVO
     * @param inItemDisList
     */
    public DataDao(LayuiPageInfo pageInfo, XyExcelDefVO defVO, List<XyExportExcelItem> inItemDisList) throws Exception {
        this.defVO = defVO;
        if (inItemDisList != null) {
            for (XyExportExcelItem item : inItemDisList) {
                if (item.isMainItem()) {
                    mainDisList.add(item);
                } else {
                    bodyDisList.add(item);
                }
            }
        }

        //初始化表头，表体数据
        initMainData(pageInfo.getData());
        initBodyData(pageInfo.getData());
    }

    /**
     * 主键列表
     *
     * @return
     */
    public List<String> getBillPkList() {
        return idList;
    }


    /**
     * 列表
     *
     * @return
     */
    public List<Map<String, Object>> getBill(String pk) {
        Map<String, Object> bill = mainMap.get(pk);
        if (bill == null) {
            return null;
        }
        List<Map<String, Object>> nowBodyList = bodyList.get(pk);
        if (nowBodyList == null || nowBodyList.size() == 0) {
            nowBodyList = new ArrayList<>();
            nowBodyList.add(bill);
        } else {
            for (Map<String, Object> temp : nowBodyList) {
                temp.putAll(bill);
            }
        }
        return nowBodyList;
    }

    /**
     * 初始化数据
     *
     * @return
     * @throws Exception
     */
    private void initMainData(List dataList) throws Exception {
        //卫语句
        if (dataList.size() <= 0) {
            return;
        }
        //取得需要反射的所有方法
        Object itemObject = dataList.get(0);
        //方法
        FetchManager fetchManager = new FetchManager(itemObject);
        Map<String, IFetch> methodMap = new HashMap<>();
        for (XyExportExcelItem item : mainDisList) {
            methodMap.put(item.getCode(), fetchManager.method(item.getCode()));
        }
        //取得主键
        IFetch idGetMethod = fetchManager.method(defVO.getHeadPk());
        Map<String, Object> newItemMap;
        String pkValue;
        Long index = 0l;
        for (Object dataItem : dataList) {
            newItemMap = new HashMap<>();
            for (XyExportExcelItem item : mainDisList) {
                IFetch m = methodMap.get(item.getCode());
                if (m == null) {
                    newItemMap.put(item.getCode(), "");
                } else {
                    newItemMap.put(item.getCode(), m.getValue(dataItem));
                }
            }
            try {
                pkValue = idGetMethod.getValue(dataItem).toString();
            } catch (Exception ex) {
                pkValue = null;
            }
            if (pkValue == null || pkValue.length() == 0) {
                pkValue = String.valueOf(index++);
            }
            idList.add(pkValue);
            newItemMap.put(defVO.getHeadPk(), pkValue);
            mainMap.put(pkValue, newItemMap);
        }
    }


    /**
     * 初始化数据
     *
     * @return
     * @throws Exception
     */
    private void initBodyData(List dataList) throws Exception {
        //卫语句
        if (bodyDisList.size() <= 0) {
            return;
        }
        if (defVO.getBody() == null || defVO.getBody().getQueryClass() == null || defVO.getBody().getQueryClass().length() < 10) {
            return;
        }
        //查询数据
        Class<?> targetClass = Class.forName(defVO.getBody().getQueryClass());
        Object impl = SpringContextHolder.getBean(targetClass);
        if (impl == null) {
            return;
        }
        String methodName = defVO.getBody().getMethodName();
        if (methodName == null || methodName.trim().length() <= 0) {
            methodName = "queryByHeadIds";
        }
        Method method = targetClass.getMethod(methodName, String.class);
        if (method == null) {
            throw new Exception("List<T> queryByHeadIds (String arg)方法不存在");
        }
        //其它的情况就调用真实对象原来的方法
        String idListStr = ListUtil.join(idList);
        Object[] args = {idListStr};
        Object bodyDbList = method.invoke(impl, args); //真实对象，方法的参数
        if (bodyDbList == null) {
            return;
        }
        List bodyDataList = (List) bodyDbList;
        if (bodyDataList.size() == 0) {
            return;
        }

        //方法
        Object itemBodyObject = bodyDataList.get(0);
        FetchManager fetchManager = new FetchManager(itemBodyObject);
        Map<String, IFetch> methodBodyMap = new HashMap<>();
        for (XyExportExcelItem bodyItem : bodyDisList) {
            methodBodyMap.put(bodyItem.getCode(), fetchManager.method(bodyItem.getCode()));
        }
        IFetch fkGetMethod = fetchManager.method(defVO.getBody().getBodyFk());

        //取得表体全部数据
        Map<String, Object> newBodyItemMap;
        String fk;
        for (Object dataItem : bodyDataList) {
            newBodyItemMap = new HashMap<>();
            for (XyExportExcelItem item : bodyDisList) {
                IFetch m = methodBodyMap.get(item.getCode());
                if (m == null) {
                    newBodyItemMap.put(item.getCode(), "");
                } else {
                    newBodyItemMap.put(item.getCode(), m.getValue(dataItem));
                }
            }
            fk = fkGetMethod.getValue(dataItem).toString();
            bodyList.put(fk, newBodyItemMap);
        }
    }

}
